2.3. Instructions
What belongs in a system instruction?
An instruction should state the agent's purpose and the decisions the model must make consistently. Deterministic validation, authorization, secrets, and data integrity belong in code or infrastructure policy, not prose the model can ignore.
What operating contract does the Ops Copilot use?
The source instruction covers five concerns:
INSTRUCTION = """\
You are the Ops Copilot, an on-call assistant for a fictional online platform.
You help engineers triage and resolve incidents quickly and safely.
Operating rules:
- Always ground your answers in the tools. Never invent incidents, services, or statuses.
- For diagnosis, inspect sample logs before recommending a fix.
- Use list_skills and load_skill when a procedure applies.
- Consult and cite the incident runbook before recommending remediation.
- State-changing actions need human approval; report the returned audit result.
- Be concise and actionable, and report tool errors instead of guessing.
"""
The exact, complete string lives in agents/python/src/agent/agent.py and is registered in MLflow during evaluation. The shortened excerpt above preserves the operating categories without creating a second canonical prompt.
Why require tool grounding explicitly?
Without a grounding rule, the model may answer from pretrained associations even when the fictional dataset says otherwise. The instruction tells it when to call tools; tests and trajectory evaluations verify whether it did. Runtime code still validates every argument and parses every database result.
Why mention logs, skills, and runbooks separately?
They serve different evidence roles:
- Logs show current symptoms.
- Skills provide the operating procedure for a class of task.
- Runbooks provide service/failure remediation knowledge.
Loading everything up front would increase context and injection exposure. The model discovers each source only when the task needs it.
Why is approval not just a prompt rule?
The instruction tells the model to propose an action. FunctionTool(require_confirmation=True) makes the runtime pause. before_tool_callback validates the target, and the data layer records the runtime user/session/invocation plus rationale. On the unauthenticated A2A path that user is synthetic, so it proves confirmation continuity rather than real-world identity. The prompt improves intent; the runtime enforces the boundary.
When should the answer be a schema instead of prose?
When the consumer is a machine. The conversational root_agent stays prose — a human reads it — and is unchanged. For downstream automation (tickets, dashboards), the course ships a second entry point whose final answer must validate against a Pydantic model:
triage_report_agent = Agent(
model=build_model(),
name="triage_report_agent",
description="Produces a schema-validated triage report for a single incident.",
instruction=REPORT_INSTRUCTION,
tools=[*ALL_TOOLS, *KNOWLEDGE_TOOLS],
output_schema=TriageReport,
)
The complete definition in report.py attaches the same budget, redaction, and error callbacks as the root agent. ADK's output_schema constrains only the final answer, so the tool loop stays available for evidence gathering. TriageReport forbids extra fields and patterns every id and slug, which makes violations loud; what happens on a violation is covered in 4.0. Typing.
Do not add schema constraints when a human-readable conversation is the real interface; unnecessary structure can limit tool use and model flexibility.
How do you review an instruction change?
Treat it like code:
- Make one behavioral change.
- Add or update an evaluation case that demonstrates the reason.
- Run offline tests, ADK trajectories, and MLflow evaluation on an explicit model.
- Review safety regressions and token growth.
- Register the new prompt version with the result.
What is the instruction checkpoint?
Read the exact INSTRUCTION and map each rule to a test, evaluation, callback, or tool boundary. Any safety-critical rule with no runtime enforcement or evidence is an identified gap, not a guarantee.